package com.wolfking.converter.transform.extend;

import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.wolfking.converter.transform.AbstractExtendTransform;
import com.wolfking.converter.util.CaesarUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;

@Slf4j
public class MoreJsonExtractTransform extends AbstractExtendTransform<String> {


    private ExtractConfig extractConfig;

    public MoreJsonExtractTransform() {

    }

    public MoreJsonExtractTransform(String extractConfig) {
        this.extractConfig = new Gson().fromJson(extractConfig, ExtractConfig.class);
    }

    @Override
    @SuppressWarnings("all")
    public String transform(Object value) {
        if (Objects.isNull(value)) {
            return "";
        }
        String beforeValue;
        if (value instanceof String) {
            beforeValue = value.toString();
        } else if (value instanceof byte[]) {
            beforeValue = new String((byte[]) value, StandardCharsets.UTF_8);
        } else {
            beforeValue = value.toString();
        }

        if (CaesarUtil.isEncrypted(beforeValue)) {
            beforeValue = CaesarUtil.decode(beforeValue);
        }

        try {
            JsonElement element = JsonParser.parseString(beforeValue);
            if (!element.isJsonArray() && !element.isJsonObject()) {
                return beforeValue;
            }
            String[][] ss = new String[extractConfig.getFields().size()][];
            for (int i = 0; i < extractConfig.getFields().size(); i++) {
                String path = extractConfig.getFields().get(i);
                element = JsonParser.parseString(beforeValue);
                List<String> list = JsonExtractTransform.extractString(element, path);
                ss[i] = list.toArray(new String[list.size()]);
            }

            List<String> append = Lists.newArrayList();
            for (int j = 0; j < ss[0].length; j++) {
                List<String> list = Lists.newArrayList();
                for (int i = 0; i < ss.length; i++) {
                    list.add(ss[i][j]);
                }
                append.add(String.format(extractConfig.getFormat(), list.toArray(new String[list.size()])));
            }
            return String.join(extractConfig.getLineSeparator(), append);
        } catch (Exception e) {
            log.warn("", e);
            return beforeValue;
        }
    }

    @Override
    public String getExampleConfig() {
        return " {\n" +
                "\t\"fields\": [\n" +
                "\t\t\"ledgercode\",\n" +
                "\t\t\"dividevalue\"\n" +
                "\t],\n" +
                "\t\"format\": \"%s(%s)\",\n" +
                "\t\"lineSeparator\": \"<BR>\"\n" +
                "}";
    }

    @Override
    public String getExampleConfigDesc() {
        return " {\n" +
                "\t\"fields\": [\n" +
                "\t\t\"列1\",\n" +
                "\t\t\"列2\"\n" +
                "\t],\n" +
                "\t\"format\": \"String.format(\".....\")\",\n" +
                "\t\"lineSeparator\": \"列风格符\"\n" +
                "}";
    }

    @Data
    private static class ExtractConfig {
        private List<String> fields;
        private String lineSeparator = "<BR>";
        private String format;
    }
}
